﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;


namespace Epicor.Pub
{
    /// <summary> 钩子</summary>
    public class HookLib
    {

        private  int WH_KEYBOARD_LL = 13;
        private IntPtr _hookWindowPtr = IntPtr.Zero;
        private static int _hHookValue = 0;            //勾子程序处理事件       
        private WinAPI32.HookHandle _KeyBoardHookProcedure;            //Hook结构 
        /// <summary> </summary>
        [StructLayout(LayoutKind.Sequential)]
        public class HookStruct
        {
            /// <summary> </summary>
            public int vkCode;
            /// <summary> </summary>
            public int scanCode;
            /// <summary> </summary>
            public int flags;
            /// <summary> </summary>
            public int time;
            /// <summary> </summary>
            public int dwExtraInfo;
        }
        /// <summary>接收SetWindowsHookEx返回值</summary>
        public delegate bool ProcessKeyHandle(HookStruct param, int wParam); 
        private static ProcessKeyHandle _clientMethod = null;//外部调用的键盘处理事件   
        /// <summary>获取大写锁定键是否按下</summary>
        public bool CapsLockStatus
        {
            get
            {
                byte[] bs = new byte[256];
                WinAPI32.GetKeyboardState(bs);
                return (bs[0x14] == 1);
            }
        }

        /// <summary>安装勾子,调用clientMethod键盘处理事件</summary>        
        public void InstallHook(ProcessKeyHandle clientMethod)      
         {         
             _clientMethod = clientMethod;                  
             if (_hHookValue == 0)   // 安装键盘钩子              
             {            
                 _KeyBoardHookProcedure = new WinAPI32.HookHandle(OnHookProc); 
                 _hookWindowPtr = WinAPI32.GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
                 _hHookValue = WinAPI32.SetWindowsHookEx(
                     WH_KEYBOARD_LL,
                     _KeyBoardHookProcedure, 
                     _hookWindowPtr,
                     0);                        
                 //如果设置钩子失败.           
                 if (_hHookValue == 0) UninstallHook(); 
             }      
         }

        ///<summary>取消钩子事件</summary>    
        public void UninstallHook()
         {
             if (_hHookValue != 0)
             {
                 bool ret = WinAPI32.UnhookWindowsHookEx(_hHookValue);
                 if (ret) _hHookValue = 0;
             }
         }
        //钩子事件内部调用,调用_clientMethod方法转发到客户端应用。  
        private static int OnHookProc(int nCode, int wParam, IntPtr lParam)    
        {
            if (nCode >= 0)     
            {            
                //转换结构           
                HookStruct hookStruct = (HookStruct)Marshal.PtrToStructure(lParam, typeof(HookStruct));     
                if (_clientMethod != null)           
                {
                    bool bl = _clientMethod(hookStruct, wParam); //调用客户提供的事件处理程序。        
                    if (bl) return 1; //1:表示拦截键盘,return 退出   
                }     
   
            }       
            return WinAPI32.CallNextHookEx(_hHookValue, nCode, wParam, lParam);   
        }
        ///<summary>发送按下虚拟键</summary>    
        public void KeyDown(Keys key)
        {
            WinAPI32.keybd_event((byte)(key), 0, 0, 0);
        }
        ///<summary>发送抬起虚拟键</summary>    
        public void KeyUp(Keys key)
        {
            const int KEYEVENTF_KEYUP = 0x2;
            WinAPI32.keybd_event((byte)key, 0, KEYEVENTF_KEYUP, 0);
        }
        ///<summary>发送虚拟键</summary>    
        public void KeyPress(Keys key)
        {
            const int VK_SHIFT = 0x10;
            const int KEYEVENTF_KEYUP = 0x2;

            if (key.GetHashCode() >=256)
            {
                WinAPI32.keybd_event(VK_SHIFT, 0, 0, 0);
                WinAPI32.keybd_event((byte)(key), 0, 0, 0);
                WinAPI32.keybd_event((byte)key, 0, KEYEVENTF_KEYUP, 0);
                WinAPI32.keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
            }
            else {
                WinAPI32.keybd_event((byte)(key), 0, 0, 0);
                WinAPI32.keybd_event((byte)key, 0, KEYEVENTF_KEYUP, 0);
            }
        }
        /////<summary>判断key是否为Ctrl||Alt||Shift键</summary>    
        //public Boolean IsCtrlAltShiftKeys(Keys key)
        //{
        //    if (key == Keys.LControlKey || key == Keys.RControlKey || key == Keys.LMenu 
        //        || key == Keys.RMenu || key == Keys.LShiftKey || key == Keys.RShiftKey) {
        //        return true;
        //    }
        //    return false;
        //}
        //public List<Keys> preKeysList = new List<Keys>();
        //public Keys GetDownKeys(Keys key)
        //{
        //    Keys rtnKey = Keys.None;
        //    foreach (Keys i in preKeysList)
        //    {
        //        if (i == Keys.LControlKey || i == Keys.RControlKey) { rtnKey = rtnKey | Keys.Control; }
        //        if (i == Keys.LMenu || i == Keys.RMenu) { rtnKey = rtnKey | Keys.Alt; }
        //        if (i == Keys.LShiftKey || i == Keys.RShiftKey) { rtnKey = rtnKey | Keys.Shift; }
        //    }
        //    return rtnKey | key;
        //}
    }
}
